<html>
<head>
<title>Flink Jobs</title>
<meta charset="UTF-8">
<link rel="alternate icon" type="image/x-icon" href="favicon.ico">
<link rel="icon" sizes="72x72" href="favicon.ico">
<link rel="apple-touch-icon-precomposed" href="favicon.ico">
<!-- Tile icon for Win8 (144x144 + tile color) -->
<meta name="msapplication-TileImage" content="favicon.ico">
</head>
<body>
	<span>
		<button onclick="toggle(this)">启动</button>
		<span>状态：<span id="state">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>
		<span>耗时：<span id="consuming">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span>
		<span>运行信息：<span id="message"></span></span>
	</span>
	<div style="margin-top: 10px">
		<textarea id="flink_jobs" rows="48" style="width: 100%"><?xml version="1.0" encoding="UTF-8"?>
<flink-jobs xmlns="http://www.10mg.cn/schema/flink-jobs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.10mg.cn/schema/flink-jobs http://www.10mg.cn/schema/flink-jobs.xsd"
	jar="\${flinkHome}/examples/streaming/WordCount.jar">
</flink-jobs></textarea>
	</div>

	<script type="text/javascript">
		/**
		 * 将可选值覆盖默认值，否则使用默认值。
		 * 
		 * @param defaults
		 *            {Object} 默认值对象
		 * @param options
		 *            {Object} 可选值对象
		 * @return 返回值覆盖后的新对象
		 */
		function extend(defaults, options) {
			if (options) {
				for ( var i in options) {
					if (typeof (options[i]) !== 'undefined') {
						defaults[i] = options[i];
					}
				}
			}
			return defaults;
		}

		/**
		 * 将查询字符串包装到网址上
		 * @param url 网址
		 * @param queryStr 查询字符串
		 */
		function wrapUrl(url, queryStr) {
			if (url.indexOf('?') < 0) {
				url += '?' + queryStr;
			} else {
				url += '&' + queryStr;
			}
			return url;
		}

		/**
		 * Ajax请求
		 * 
		 * @param options
		 *            {Object} 选项
		 */
		function ajax(options) {
			var time = new Date().getTime();
			options = extend({
				type : 'GET',
				url : '',
				async : true,
				cache : true,
				beforeSend : function(xhr, options) {
				},
				complete : function(xhr, status) {
				}
			}, options);
			var xhr = null, url = options.url, isGet = options.type
					.toUpperCase() == 'GET';
			if (isGet) {
				var isAt = false;
				if (typeof options.data === 'string') {
					url = wrapUrl(url, options.data);
					isAt = true;
				}
				if (!options.cache) {
					if (isAt) {
						url += '&_=' + time;
					} else {
						url = wrapUrl(url, '_=' + time);
					}
				}
			}
			if (window.XMLHttpRequest) {// 所有新型浏览器
				xhr = new XMLHttpRequest();
			} else if (window.ActiveXObject) {// 兼容IE5和IE6
				xhr = new ActiveXObject("Microsoft.XMLHTTP");
			}
			if (xhr == null) {
				throw new Error(i18n('createXMLHttpRequestError'));
			} else {
				xhr.onreadystatechange = function() {
					if (xhr.readyState == 4) {
						options.complete(xhr, status);
						var status = xhr.status;
						if (status == 200) {
							if (options.success) {
								var data = xhr.responseText;
								if (options.dataType == 'json') {
									if (data) {
										if (typeof JSON.parse == 'function') {
											data = JSON.parse(data);
										} else {// 兼容没有JSON.parse的浏览器
											eval('data = ' + data);
										}
									} else {
										if (options.error) {
											options.error(xhr);
										}
									}
								}
								options.success(data, xhr);
							}
						} else {
							if (options.error) {
								options.error(xhr);
							}
						}
					}
				};
				xhr.open(options.type, url, options.async);
				if (options.contentType) {
					xhr.setRequestHeader('Content-type', options.contentType);
				}
				options.beforeSend(xhr, options);
				xhr.send(options.data);
			}
		}

		function toggle(e) {
			message.innerText = '';
			if (e.innerText == '启动') {
				start(e);
			} else {
				stop(e);
			}
		}
		
		function errorResolve(xhr, msg, e) {
			if (xhr.status == 404) {
				message.innerText = '无法连接到远程服务！';
			} else {
				message.innerText = '请求远程服务发生错误！';
			}
		}
		
		var timerId, milliseconds;
		function start(e) {
			milliseconds = new Date().getTime();
			ajax({
				contentType : 'application/json',
				dataType : 'json',
				type : 'post',
				url : 'flinkjobs/start',
				cache : false,
				processData : false,
				data : JSON.stringify({
					'flink-jobs' : flink_jobs.value
				}),
				async : true,
				success : function(response, status, xhr) {
					var jobId = response.data;
					if (response.success && jobId) {
						updateConsuming();
						state.innerText = 'SUBMITTED';
						e.setAttribute('jobId', jobId);
						e.innerText = '停止';
						timerId = setTimeout(function() {
							monitor(e);
						}, 3000);
					} else {
						message.innerText = response.message?response.message:'请求远程服务发生错误！';
					}
				},
				error : errorResolve
			});
		}
		
		function updateConsuming() {
			var timeConsuming = new Date().getTime() - milliseconds;
			if (timeConsuming < 1000) {
				consuming.innerText = timeConsuming + 'ms';
			} else if (timeConsuming < 60000) {
				consuming.innerText = parseInt(timeConsuming/1000) + 's';
			} else if (timeConsuming < 3600000) {
				var seconds = timeConsuming/1000, minutes = seconds/60;
				consuming.innerText = Math.floor(minutes) + 'm' + parseInt(seconds)%60 + 's';
			} else if (timeConsuming < 216000000) {
				var seconds = timeConsuming/1000, minutes = seconds/60, hours = minutes/60;
				consuming.innerText = Math.floor(hours) + 'h' + parseInt(minutes)%60 + 'm' + parseInt(seconds)%60 + 's';
			} else {
				var seconds = timeConsuming/1000, minutes = seconds/60, hours = minutes/60, days = hours/24;
				consuming.innerText = Math.floor(days) + 'd' + parseInt(hours)%60 + 'h' + parseInt(minutes)%60 + 'm' + parseInt(seconds)%60 + 's';
			}
		}
		
		function monitor(e) {
			//clearTimeout(timerId);
			ajax({
				contentType : 'application/json',
				dataType : 'json',
				type : 'post',
				url : 'flinkjobs/info',
				cache : false,
				processData : false,
				data : JSON.stringify({
					'jobId' : e.getAttribute('jobId')
				}),
				async : true,
				success : function(response, status, xhr) {
					var data = response.data;
					if (response.success && data) {
						var status = data.state;
						state.innerText = status;
						if (data.message) {
							message.innerText = data.message;
						}
						updateConsuming();
						if (status == 'FINISHED' || status == 'CREATED' || status == 'FAILED') {
							e.innerText = '启动';
						} else {
							timerId = setTimeout(function() {
								monitor(e);
							}, 3000);
						}
					} else {
						message.innerText = response.message?response.message:'请求远程服务发生错误！';
					}
				},
				error : errorResolve
			});
		}
		
		function stop(e) {
			clearTimeout(timerId);
			ajax({
				contentType : 'application/json',
				dataType : 'json',
				type : 'post',
				url : 'flinkjobs/stop',
				cache : false,
				processData : false,
				data : JSON.stringify({
					'jobId' : e.getAttribute('jobId')
				}),
				async : true,
				success : function(response, status, xhr) {
					updateConsuming();
					if (response.success) {
						if (response.message) {
							message.innerText = response.message;
							e.innerText = '启动';
							state.innerText = 'FINISHED';
						} else {
							timerId = setTimeout(function() {
								monitor(e);
							}, 3000);
						}
					} else {
						message.innerText = response.message;
					}
				},
				error : errorResolve
			});
		}
	</script>
</body>
</html>
